﻿using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using RainEngine.SceneNodes;

namespace RainEngine.Controllers
{
    /// <summary>
    /// 自由相机的控制器。
    /// </summary>
    public class FreeCameraController : Controller
    {
        #region 构造函数和成员变量
        /// <summary>
        /// 要控制的相机对象。
        /// </summary>
        private CameraSceneNode camera;

        /// <summary>
        /// 光标的初始位置，位于屏幕中央，每一帧都会将鼠标放置到屏幕中央。
        /// </summary>
        private MouseState originalMouseState;

        /// <summary>
        /// 创建一个新FreeCameraController对象。
        /// </summary>
        /// <param name="engine">引擎</param>
        public FreeCameraController(RainGE engine): base(engine)
        {
            
        }
        #endregion

        /// <summary>
        /// 主控制逻辑。
        /// </summary>
        /// <param name="gameTime"></param>
        public override void ControllerAction(GameTime gameTime)
        {
            if (camera == null)
            {
                camera = (CameraSceneNode)controlledNode;
                //将鼠标初始位置设置为屏幕中央
                Mouse.SetPosition(engine.GraphicsDevice.Viewport.Width / 2, engine.GraphicsDevice.Viewport.Height / 2);
                originalMouseState = Mouse.GetState();                
            }

            float timeDifference = (float)gameTime.ElapsedGameTime.TotalMilliseconds / 1000.0f;
            ProcessInput(timeDifference);
        }

        private void ProcessInput(float ellapsedTime)
        {
            //相机是否旋转
            //bool isRotation = false;
            //相机的滚动
            float cameraRoll = 0;
            //相机的俯仰
            float cameraPitch = 0;
            //相机的左右旋转
            float cameraYaw = 0;
            //相机的移动
            float movement = 0;

            ////相机每帧旋转和移动距离
            float rotationPerFrame= ellapsedTime *camera.RotationSpeed  ;
            float movementPerFrame = ellapsedTime * camera.MovementSpeed;

            if (engine.IsActive)
            {
                MouseState currentMouseState = Mouse.GetState();
                //如果按住鼠标左键并且鼠标发生移动
                if (Input.MouseLeftButtonPressed && currentMouseState != originalMouseState)
                {
                    //获取鼠标在水平和竖直方向的移动大小
                    float xDifference = currentMouseState.X - originalMouseState.X;
                    float yDifference = currentMouseState.Y - originalMouseState.Y;

                    //水平方向的移动控制相机的左右旋转
                    cameraYaw += rotationPerFrame * xDifference;
                    //竖直方向的移动控制相机的上下旋转
                    cameraPitch -= rotationPerFrame * yDifference;

                    //将光标重新设置到屏幕的中央
                    Mouse.SetPosition(originalMouseState.X, originalMouseState.Y);
                }
            }

            //键盘控制相机的前后左右移动和翻滚
            if (Input.KeyboardUpPressed || Input.Keyboard.IsKeyDown(Keys.W))
                movement += movementPerFrame;
            if (Input.KeyboardDownPressed || Input.Keyboard.IsKeyDown(Keys.S))
                movement -= movementPerFrame;
            if (Input.KeyboardRightPressed || Input.Keyboard.IsKeyDown(Keys.D))
                cameraYaw += rotationPerFrame;
            if (Input.KeyboardLeftPressed || Input.Keyboard.IsKeyDown(Keys.A))
                cameraYaw -= rotationPerFrame;
            if (Input.Keyboard.IsKeyDown(Keys.Q))
                cameraRoll -= rotationPerFrame;
            if (Input.Keyboard.IsKeyDown(Keys.E))
                cameraRoll += rotationPerFrame;

            //如果相机旋转
            if (cameraRoll != 0 || cameraPitch != 0 || cameraYaw != 0)
            {
                Vector3 angleRotation = new Vector3(cameraPitch, cameraYaw, cameraRoll );
                camera.AngleRotation += angleRotation;
                //设置相机的旋转
                camera.Pose.Rotation = Quaternion.CreateFromYawPitchRoll(MathHelper.ToRadians(-camera.AngleRotation.Y), MathHelper.ToRadians(camera.AngleRotation.X), MathHelper.ToRadians(camera.AngleRotation.Z));
                
                //isDirty设为true表示需要更新相机
                isDirty = true;
                //isRotation = true;
            }

            //如果相机移动
            if (movement != 0)
            {
                //isDirty设为true表示需要更新相机
                isDirty = true;

                //设置相机的位置
                camera .Pose .Position +=camera.GetMoveForwardVector(movement);
            }
            
            if (isDirty)
            {
                camera.UpdateViewMatrix(true);
                isDirty = false;
            }
        }
    }
}
